package com.qxcy.gzy.util;

import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.support.annotation.IntDef;

import java.io.File;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Date;

//电机与制动器切换启动操作（小电机对应制动器1；大电机对应制动器2）
public class SerialPortUtils {
    public static final String EM_STATUS = "EM_STATUS";
    public static final String CURRENT_EM = "CURRENT_EM";
    public static final String EM_BIG_STATUS = "EM_BIG_STATUS";
    public static final String EM_SMALL_STATUS = "EM_SMALL_STATUS";

    //-1:未启动，0：等待状态，1：运行状态
    public static final int EM_STATUS_STOP = -1;
    public static final int EM_STATUS_WAIT = 0;
    public static final int EM_STATUS_RUN = 1;

    @IntDef({EM_STATUS_STOP, EM_STATUS_WAIT, EM_STATUS_RUN})
    @Retention(RetentionPolicy.SOURCE)
    public @interface EMStatus {

    }

    public static final int SerialPortDefault = 100;//1000ms
    public static final int SerialPortSwitch = 150;//2000ms
    public static final int SerialPortReadSwitch = 80;//800ms

    public static final int ElectricMachineryBig = 0x001;//大电机
    public static final int ElectricMachinerySmall = 0x002;//小电机
    public static final int BrakeForBig = 0x001;//制动器2
    public static final int BrakeForSmall = 0x002;//制动器1
    public static final int BrakeActionOpen = 0x001;//打开制动器
    public static final int BrakeActionClose = 0x002;//打开制动器
    public static final int EMActionStart = 0x001;//电机启动
    public static final int EMActionStop = 0x002;//电机停止
    public static final int EMActionWait = 0x003;//电机等待
    public static final int EMActionRun = 0x004;//电机运行
    public static final int ReadBrakeSmall = 0x001;//读制动器1寄存器
    public static final int ReadBrakeBig = 0x002;//读制动器2寄存器
    public static final int ReadEM = 0x003;//读电机寄存器
    public static final int SCStart = 0x01;//启动刹车
    public static final int SCStop = 0x00;//停止刹车

    private static int getBrake(@ElectricMachineryType int type) {
        return type == ElectricMachineryBig ? BrakeForBig : BrakeForSmall;
    }


    @IntDef({SCStart, SCStop})
    @Retention(RetentionPolicy.SOURCE)
    public @interface SCAction {

    }

    @IntDef({ElectricMachineryBig, ElectricMachinerySmall})
    @Retention(RetentionPolicy.SOURCE)
    public @interface ElectricMachineryType {

    }

    @IntDef({BrakeForBig, BrakeForSmall})
    @Retention(RetentionPolicy.SOURCE)
    public @interface BrakeType {

    }

    @IntDef({EMActionStart, EMActionStop, EMActionWait, EMActionRun})
    @Retention(RetentionPolicy.SOURCE)
    public @interface EMAction {

    }

    @IntDef({BrakeActionOpen, BrakeActionClose})
    @Retention(RetentionPolicy.SOURCE)
    public @interface BrakeAction {

    }

    @IntDef({ReadBrakeSmall, ReadBrakeBig, ReadEM})
    @Retention(RetentionPolicy.SOURCE)
    @interface ReadType {

    }

    private static final byte empty = 0x00;
    public static final byte typeRead = 0x03;//读命令
    public static final byte typeWrite = 0x06;//写命令
    //从机地址
    public static final byte addressControl = 0x02;//控制板地址
    public static final byte addressBrakeSmall = 0x03;//小电机制动器
    public static final byte addressBrakeBig = 0x04;//大电机制动器
    //寄存器地址
    public static final byte brakeStatusSmall = 0x01;//制动器寄存器1地址(0 是关闭，1是打开)
    public static final byte brakeStatusBig = 0x02;//制动器寄存器2地址(0 是关闭，1是打开)
    public static final byte addressEMStatus = 0x1A;//电机状态读地址
    public static final byte addressSC = 0x03;//刹车装置地址
    public static final byte addressDistance = 0x18;//读取运动距离寄存器地址
    public static final byte[] addressPower = {0x10, 0x01};//力量设置寄存器地址
    //地址
    public static final byte addressEMControl = 0x07;//电机控制(1：启动电机；0：停止电机)地址
    //（0：USR_IDLE闲置状态；1：USR_INIT初始化；2：USR_START启动状态；3：USR_FIND_ZERO找零点；
    // 4：USR_RUN运行状态；5：USR_STOP停止状态；6：USR_WAIT等待；7：USR_FAULT故障，（故障后控制器自动停止运行））

    //读取运动距离命令
    public static byte[] getEDCommand(@ElectricMachineryType int type) {
        byte address = type == ElectricMachineryBig ? addressBrakeBig : addressBrakeSmall;
        return CRCChecker.getSendBuf(new byte[]{address, typeRead, empty, addressDistance, empty, 0x01, empty, empty});
    }

    //设置力量命令
    public static byte[] getPowerCommand(@ElectricMachineryType int type, int weight) {
        byte address = type == ElectricMachineryBig ? addressBrakeBig : addressBrakeSmall;
        return CRCChecker.getSendBuf(new byte[]{address, typeWrite, addressPower[0], addressPower[1], empty, intToByte(weight), empty, empty});
    }

    /**
     * 启动或者停止刹车装置
     */
    public static byte[] getSCCommand(@SCAction int action) {
        return CRCChecker.getSendBuf(new byte[]{addressControl, typeWrite, empty, addressSC, empty, (byte) action, empty, empty});
    }

    /**
     * 开启或者停止电机命令
     *
     * @param type   电机类型
     * @param action 动作类型
     */
    public static byte[] getEMCommand(@ElectricMachineryType int type, @EMAction int action) {
        byte addBrake = type == ElectricMachineryBig ? addressBrakeBig : addressBrakeSmall;
        byte act;
        switch (action) {
            case EMActionStart:
                act = (byte) 0x01;
                break;
            case EMActionStop:
                act = (byte) 0x00;
                break;
            case EMActionWait:
                act = (byte) 0x03;
                break;
            case EMActionRun:
                act = (byte) 0x02;
                break;
            default:
                act = (byte) 0x03;
                break;
        }
        //比如：开启电机（0x01,0x06,0x00,0x07,0x00,0x01,0xxx,0xxx）后两位为校验位
        return CRCChecker.getSendBuf(new byte[]{addBrake, typeWrite, empty, addressEMControl, empty, act, empty, empty});
    }

    /**
     * 读取寄存器命令
     *
     * @param emType 电机类型
     * @param type   寄存器类型
     */
    public static byte[] getReadCommand(@ElectricMachineryType int emType, @ReadType int type) {
        byte addSM = (type == ReadEM) ? (emType == ElectricMachineryBig ? addressBrakeBig : addressBrakeSmall) : addressControl;
        byte add;
        switch (type) {
            case ReadEM:
                add = addressEMStatus;
                break;
            case ReadBrakeSmall:
                add = brakeStatusSmall;
                break;
            case ReadBrakeBig:
                add = brakeStatusBig;
                break;
            default:
                add = addressEMStatus;
                break;
        }
        //读制动器：02 03 00 02 00 01 xx xx
        return CRCChecker.getSendBuf(new byte[]{addSM, typeRead, empty, add, empty, 0x01, empty, empty});
    }

    /**
     * 切换寄存器命令
     *
     * @param type   制动器类型
     * @param action 制动器操作，打开或者关闭
     */
    public static byte[] getBradeCommand(@BrakeType int type, @BrakeAction int action) {
        byte act = action == BrakeActionOpen ? (byte) 0x01 : (byte) 0x00;
        byte add = type == BrakeForBig ? brakeStatusBig : brakeStatusSmall;
        //打开大电机：02 06 00 02 00 01 xx xx
        return CRCChecker.getSendBuf(new byte[]{addressControl, typeWrite, empty, add, empty, act, empty, empty});
    }

    /**
     * 切换寄存器命令
     *
     * @param type   电机类型
     * @param action 制动器操作，打开或者关闭
     */
    public static byte[] getBradeCommandFromEM(@ElectricMachineryType int type, @BrakeAction int action) {
        return getBradeCommand(getBrake(type), action);
    }

    //byte 与 int 的相互转换
    public static byte intToByte(int x) {
        return (byte) x;
    }

    public static int byte2Int(byte b) {
        return (int) (b & 0xff);
    }

    public static byte[] intToByteArray(int i) {
        byte[] result = new byte[4];
        result[0] = (byte) ((i >> 24) & 0xFF);
        result[1] = (byte) ((i >> 16) & 0xFF);
        result[2] = (byte) ((i >> 8) & 0xFF);
        result[3] = (byte) (i & 0xFF);
        return result;
    }

    public static int byteArrayToInt(byte[] bytes) {
        int value = 0;
        for (int i = 0; i < 4; i++) {
            int shift = (3 - i) * 8;
            value += (bytes[i] & 0xFF) << shift;
        }
        return value;
    }

    public static void showSerialDialog(Context context, String title, String message) {
        if (context != null)
            new AlertDialog.Builder(context)
                    .setTitle(title)
                    .setMessage(message)
                    .setNegativeButton("确定", new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            dialog.dismiss();
                        }
                    }).create().show();
    }

    public static void showSwitchDialog(Context context, String title, String message, DialogInterface.OnClickListener listener) {
        if (context != null)
            new AlertDialog.Builder(context)
                    .setTitle(title)
                    .setMessage(message)
                    .setPositiveButton("确定", listener)
                    .setNegativeButton("取消", new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            dialog.dismiss();
                        }
                    }).create().show();
    }


    public static void saveLocalLog(String title, String message) {
        LocalLogUtils.saveLocalLog(title, message, ConstantCore.LOG_SERIAL_PATH);
    }

    public static void saveLocalDailyLog(String message) {
        LocalLogUtils.saveLocalDailyLog(new Date(), message, ConstantCore.LOG_SERIAL_PATH);
    }

    public static void saveLoaclELog(String message) {
        String path = ConstantCore.LOG_SERIAL_PATH + File.separator + "exercise";
        LocalLogUtils.saveLocalDailyLog(new Date(), message, path);
    }
}